<?php

/**
 * AK_DBHelper是一个基于Mysqli封装的简单、灵活、上手快速的一个MySQL操作类
 *                                  -----   2021.09.28
 * 
 *　　　　　　　　┏┓　　　┏┓+ +
 *　　　　　　　┏┛┻━━━┛┻┓ + +
 *　　　　　　　┃　　　　　　　┃ 　
 *　　　　　　　┃　　　━　　　┃ ++ + + +
 *　　　　　　 ████━████ ┃+
 *　　　　　　　┃　　　　　　　┃ +
 *　　　　　　　┃　　　┻　　　┃
 *　　　　　　　┃　　　　　　　┃ + +
 *　　　　　　　┗━┓　　　┏━┛
 *　　　　　　　　　┃　　　┃　　　　　　　　　　　
 *　　　　　　　　　┃　　　┃ + + + +
 *　　　　　　　　　┃　　　┃　Code is far away from bug with the animal protecting　　　　　　　
 *　　　　　　　　　┃　　　┃ + 神兽保佑,永无bug　　
 *　　　　　　　　　┃　　　┃　　+　　　　　　　　　
 *　　　　　　　　　┃　 　　┗━━━┓ + +
 *　　　　　　　　　┃ 　　　　　　　┣┓\
 *　　　　　　　　　┃ 　　　　　　　┏┛/
 *　　　　　　　　　┗┓┓┏━┳┓┏┛ + + + +
 *　　　　　　　　　　┃┫┫　┃┫┫
 *　　　　　　　　　　┗┻┛　┗┻┛+ + + +
 *-------------------------------------------------------------------------
 * @var host 数据库地址
 * @var dbname 数据库名
 * @var user 用户名
 * @var dbpwd 密码
 * @var link 数据库句柄
 * @var sql 生成的SQL语句
 * @var charset 数据库编码
 * @var prefix 数据表前缀
 * @var options SQL查询条件
 *------------------------------- 
 * @author LXS                  |
 * @version 1.0                 |
 * @since 1.0                   |
 * @copyright https://inik.cc/  |
 * ------------------------------
 */
class AK_DBHelper
{
    private $host;
    private $dbname;
    private $user;
    private $dbpwd;
    private $link;
    private $sql;
    private $charset;
    private $prefix;
    private $options = [];

    public function __construct($conf)
    {
        $this->host = $conf['DB_HOST'];
        $this->dbname = $conf['DB_NAME'];
        $this->user = $conf['DB_USER'];
        $this->dbpwd = $conf['DB_PWD'];
        $this->charset = $conf['DB_CHARSET'];
        $this->prefix = $conf['DB_PERFIX'];
        $this->link = $this->getDB();
        $this->initOptions();
    }
    /**
     * 返回SQL语句
     * 
     * @access public
     * @return string SQL语句
     */
    public function sql()
    {
        return $this->sql;
    }
    /**
     * 初始化MySQL链接
     * 
     * @access public
     * @return object 当前对象 
     */
    public function getDB()
    {
        $link = new mysqli($this->host, $this->user, $this->dbpwd, $this->dbname);
        if ($link->connect_error <> 0) {
            die($link->connect_error);
        }
        mysqli_set_charset($link, $this->charset);
        return $link;
    }
    /**
     * 初始化操作参数数组
     * 
     * @access public
     * @return void
     */
    public function initOptions()
    {
        $arr = array('field', 'where', 'select', 'limit', 'table', 'order', 'update', 'keys', 'values');
        foreach ($arr as $value) {
            $this->options[$value] = "";
        }
    }
    /**
     * 构造SQL查询表名
     * 
     * @access public
     * @param string $tablename 数据表名
     * @return object 当前对象
     */
    public function table($tablename)
    {
        if (!empty($tablename)) {
            if (is_string($tablename)) {
                $this->options['table'] = "`" . $this->prefix . $tablename . "`";
            }
        }
        return $this;
    }
    /**
     * 构造SQL欲查询目标字段
     * 
     * @access public
     * @param mixed $field 目标字段
     * @return object 当前对象
     */
    public function field($field = '*')
    {
        if (!empty($field)) {
            if (is_string($field)) {
                $this->options['field'] = $field;
            } else if (is_array($field)) {
                $this->options['field'] = join(',', $field);
            }
        }
        return $this;
    }
    /**
     * 构造SQL查询条件
     * 
     * @access public
     * @param mixed $where 查询字段；如果为二维数组，则第二维只能传入两个值的索引数组，即：[min,max]。示例：where(['id'=>[1,3]]) 查询id属于1~3范围的记录
     * @param mixed $condition 查询条件 默认：=
     * @return object 当前对象
     */
    public function where($where = null, $condition = '=')
    {
        if (!empty($where)) {
            if (is_string($where)) {
                $this->options['where'] = ' where ' . $where;
            } else if (is_array($where)) {
                $str = " where ";
                //判断是否是关联数组
                if (array_keys($where) !== range(0, count($where) - 1)) {
                    foreach ($where as $key => $value) {
                        //拼接组合查询语句
                        if (is_string($condition)) {
                            //范围查询
                            if (is_array($value)) {
                                if (count($value) != 1) {
                                    $str .= '`' . $key . "` >= '" . $value[0] . "' AND " . '`' . $key . "` <= '" . $value[1] . "',";
                                } else {
                                    $str .= '`' . $key . "` " . $condition . " '" . $value[0] . "',";
                                }
                            } else if (is_string($value)) {
                                $str .= '`' . $key . "` " . $condition . " '" . $value . "',";
                            } else {
                                $str .= '`' . $key . "` " . $condition . " " . $value . ",";
                            }
                        }
                    }
                    $str = substr($str, 0, strlen($str) - 1);
                    $this->options['where'] = $str;
                }
            }
        } else {
            $this->options['where'] = "";
        }
        return $this;
    }
    /**
     * 构造SQL查询偏移量
     * 
     * @access public
     * @param mixed $limit 查询偏移量[开始,条数]
     * @return object 当前对象
     */
    public function limit($limit)
    {
        if (!empty($limit)) {
            if (is_string($limit)) {
                $this->options['limit'] = ' limit ' . $limit;
            } else if (is_array($limit)) {
                $this->options['limit'] = ' limit ' . join(',', $limit);
            }
        } else {
            $this->options['limit'] = '';
        }
        return $this;
    }
    /**
     * 构造SQL查询排序方式
     * 
     * @access public
     * @param string $key 字段
     * @param string $order 排序方式  DESC:倒序 ASC：正序
     * @return object 当前对象
     */
    public function order($key, $order)
    {
        if (!empty($order)) {
            if (is_string($order)) {
                $this->options['order'] = 'ORDER BY ' . $key . ' ' . $order;
            }
        } else {
            $this->options['order'] = '';
        }
        return $this;
    }
    /**
     * 执行SQL插入
     * 
     * @access public
     * @param array $data 插入值
     * @return boolean 插入成功/失败
     * @return string 请传入参数
     */
    public function insert($data)
    {
        if (!empty($data)) {
            if (is_array($data)) {
                $keystr = '';
                $valuestr = '';
                if (array_keys($data) !== range(0, count($data) - 1)) {
                    foreach ($data as $key => $value) {
                        $keystr .= '`' . $key . '` ,';
                        $valuestr .= "'" . $value . "',";
                    }
                    $keystr = substr($keystr, 0, strlen($keystr) - 1);
                    $valuestr = substr($valuestr, 0, strlen($valuestr) - 1);
                    $this->options['keys'] = $keystr;
                    $this->options['vals'] = $valuestr;
                    $sql = 'INSERT INTO %TABLE% (%KEYS%) VALUES (%VALUES%)';
                    $sql = str_replace(
                        array(
                            '%TABLE%',
                            '%KEYS%',
                            '%VALUES%'
                        ),
                        array(
                            $this->options['table'],
                            $this->options['keys'],
                            $this->options['vals']
                        ),
                        $sql
                    );
                    $this->sql = $sql;
                    return $this->exec($this->sql);
                }
            }
        }
        return '请传入参数';
    }
    /**
     * 执行SQL删除
     * 
     * @access public
     * @return boolean 执行结果：true 成功 false 失败
     */
    public function delete()
    {
        $sql = 'DELETE FROM %TABLE% %WHERE%';
        $sql = str_replace(
            array(
                '%TABLE%',
                '%WHERE%'
            ),
            array(
                $this->options['table'],
                str_replace(',', ' and ', $this->options['where']),
            ),
            $sql
        );
        $this->sql = $sql;
        return $this->exec($this->sql);
    }
    /**
     * 执行SQL更新
     * 
     * @access public
     * @param array $data 更新数据
     * @return boolean true/false
     * @return string 请传入参数
     */
    public function update($data)
    {
        if (!empty($data)) {
            if (is_string($data)) {
                $this->options['update'] = $data;
            } else if (is_array($data)) {
                //判断是否是关联数组
                $str = "";
                if (array_keys($data) !== range(0, count($data) - 1)) {
                    foreach ($data as $key => $value) {
                        //拼接组合查询语句
                        $str .= '`' . $key . "` = '" . $value . "',";
                    }
                    $str = substr($str, 0, strlen($str) - 1);
                    $this->options['update'] = $str;
                }
            }
            $sql = 'UPDATE %TABLE% SET %UPDATE% %WHERE%';
            $sql = str_replace(
                array(
                    '%TABLE%',
                    '%UPDATE%',
                    '%WHERE%'
                ),
                array(
                    $this->options['table'],
                    $this->options['update'],
                    $this->options['where']
                ),
                $sql
            );
            $this->sql = $sql;
            return $this->exec($this->sql);
        }
        return '请传入参数';
    }
    /**
     * 执行SQL查询
     * 
     * @access public
     * @return array 查询结果集
     */
    public function select()
    {
        $sql = 'SELECT %FIELD% FROM %TABLE% %WHERE% %ORDER% %LIMIT%';
        $sql = str_replace(
            array(
                '%FIELD%',
                '%TABLE%',
                '%WHERE%',
                '%ORDER%',
                '%LIMIT%'
            ),
            array(
                $this->options['field'],
                $this->options['table'],
                str_replace(',', ' and ', $this->options['where']),
                $this->options['limit'],
                $this->options['order']
            ),
            $sql
        );
        $this->sql = $sql;
        return $this->query($this->sql);
    }
    /**
     * 执行有结果集查询
     * 
     * @access public
     * @param string $sql SQL语句
     * @return array $data 结果集
     */
    public function query($sql)
    {
        $res = $this->link->query($sql);
        if ($res && $res->num_rows>0) {
            while ($row = $res->fetch_assoc()) {
                $data[] = $row;
            }
        }
        if (empty($data)) {
            return 'Query result null';
        }
        return $data;
    }
    /**
     * 执行无结果集查询
     * 
     * @access public
     * @param string $sql SQL语句
     * @return boolean true/false
     */
    public function exec($sql)
    {
        $re  = $this->link->query($sql);
        if ($re) {
            return true;
        }
        return false;
    }
}
